/**
 * Simple lexer application, parse input tokens.
 * Variation on code from : "Language Implementation Patterns", Terence Parr
 */
package org.berlin.octane.compiler.lang;

/**
 * Basic lexer, collect tokens
 */
public class VisitorSimpleLexer extends VisitorBaseLexer {
    
    private final static String[] tokenNames = {
        "XN/A",
        "XEOF",
        "XL_PAREN", 
        "XR_PAREN",
        "XDIGIT",
        "XPLUS",
    };        
           
    /**
     * Constructor for ListLexer.
     * 
     * @param input String
     */
    public VisitorSimpleLexer(String input) {
        super(input);
    }
    
    /**
     * Return token name.
     * 
     * @param x int
     * @return String
     */
    public String getTokenName(int x) {
        return tokenNames[x];
    }
        
    /**
     * Scan for next token.
     * 
     * @return Token
     */
    public VisitorToken nextToken() {
        while (c() != EOF) {
            switch (c()) {
                case ' ':
                case '\t':
                case '\n':
                case '\r':
                    consumeWhitespace();
                    continue;            
                case '(':
                    consume();
                    return new VisitorToken(VisitorToken.L_PAREN, "(");
                case ')':
                    consume();
                    return new VisitorToken(VisitorToken.R_PAREN, ")");
                case '+':
                    consume();
                    return new VisitorToken(VisitorToken.PLUS, "+");
                default:
                    if (this.isDigit()) {
                        return scanInteger();
                    }
                    final int code = (int) c();
                    throw new Error("invalid character: {" + c() + "} code:" + code);
            }
        }
        return new VisitorToken(EOF_TYPE, "_EndOfFile_");
    }

    /**
     * Scan for a token name/integer.
     * 
     * @return Token
     */
    public VisitorToken scanInteger() {
        final StringBuilder buf = new StringBuilder();
        do {
            buf.append(c());
            consume();
        } while (isDigit());        
        return new VisitorToken(VisitorToken.INTEGER, buf.toString());
    }
    
    /**
     * Check if character is a letter.
     * 
     * @return boolean
     */
    public boolean isLetter() {
        return (c() >= 'a') && (c() <= 'z') || (c() >= 'A') && (c() <= 'Z');
    }
    /**
     * Check if character is a digit.
     * 
     * @return boolean
     */
    public boolean isDigit() {
        return (c() >= '0') && (c() <= '9');
    }
    
    /**
     * Consume and detect whitespace.
     */
    public void consumeWhitespace() {
        while (c() == ' ' || c() == '\t' || c() == '\n' || c() == '\r') {                   
            consume();
        }
    }

    public static String name(final int i) {
        return tokenNames[i];
    }
    
} // End of the class
